use sysinfo::{Pid,PidExt};
use clap::Parser;
pub mod process;
pub mod cache;


// #[derive(Parser, Debug)]
// #[clap(author, version, about = "Print process memory or shared file cache", long_about = None)]
// struct Args {
    
//     #[clap(short, long, help="Print only the process's memory\nThe priority is higher than top")]
//     pid: Option<Pid>,
    
//     #[clap(short, long, help="Prints the memory of the named process\nThe priority is higher than pid")]
//     name: Option<String>,

//     #[clap(short, long, help="Prints the top number of processes in memory")]
//     top: Option<usize>,
// }



/**
subcommands:
    - proc:
        about: Print process memory
        args:
            - pid:
                help: Print only the process's memory\nThe priority is higher than top
                short: p
                takes_value: true
            - name:
                help: Prints the memory of the named process\nThe priority is higher than pid
                short: n
                takes_value: true
            - top:
                help: Prints the top number of processes in memory
                short: t
                takes_value: true
    - cache:
        about: Print shared file cache
        args:
            - top:
                help: Prints the top number of file cache
                short: t
                takes_value: true
*/

#[derive(Parser)]
#[clap(author, version, about = "Print process memory or shared file cache", long_about = None)]
struct Cli {
    #[clap(subcommand)]
    subcmd: Subcmd,
}

#[derive(clap::Subcommand)]
enum Subcmd {
    Proc(Proc),
    Cache(Cache),
}

#[derive(Parser)]
#[clap(about = "Print shared file cache", long_about = None)]
struct Cache {
    #[clap(short, long, help="Prints the top number of file cache")]
    top: Option<usize>,

    #[clap(short, long, help="Prints the process's file cache")]
    pid: Option<Pid>,
}

#[derive(Parser)]
#[clap(about = "Print process memory", long_about = None)]
struct Proc {
    #[clap(short, long, help="Print only the process's memory\nThe priority is higher than top")]
    pid: Option<Pid>,
    
    #[clap(short, long, help="Prints the memory of the named process\nThe priority is higher than pid")]
    name: Option<String>,

    #[clap(short, long, help="Prints the top number of processes in memory")]
    top: Option<usize>,
}



fn main() {

    let args = Cli::parse();

    // 解析 subcommand， proc和cache
    match args.subcmd {
        Subcmd::Proc(Proc { pid, name, top }) => {
        //    println!("pid is {:?} name is {:?}  top is {:?}", pid, name, top);
            handing_proc(name,pid,top);
        },
        Subcmd::Cache(Cache { top, pid }) => {
            handing_cache(top, pid);
        },
    }
    
   
}

// proc subcommand with name pid and top
fn handing_proc(args_name:Option<String>, args_pid:Option<Pid>, args_top:Option<usize>) {
    let name:String;
    let flag_name;
    match args_name {
        Some(n) => {flag_name= true;name = n;},
        None => {flag_name= false;name=String::new()},
    };

    let mut pid:Pid = Pid::from_u32(0);
    let flag_pid;
    match args_pid {
        Some(p) => {flag_pid = true;pid = p;},
        None => {flag_pid= false;},
    };

    let mut top:usize = 0;
    let flag_top;
    match args_top {
        Some(t) => {flag_top = true;top = t;},
        None => {flag_top= false;},
    };

    let all_processes = process::get_all_processinfo();

    if flag_name {
        process::print_process_info_by_name(&name, &all_processes);
    } else if flag_pid {
        process::print_process_info_by_pid(&pid, &all_processes);
    } else if flag_top {
        process::print_provesses_vector(&all_processes[0..top]);
    } else {
        process::print_provesses_vector(&all_processes);
    }
}

#[allow(unused_assignments)]
fn handing_cache(args_top:Option<usize>, args_pid:Option<Pid>) {

    let mut top:usize = 0;
    let flag_top;
    match args_top {
        Some(t) => {flag_top = true;top = t;},
        None => {flag_top= false;},
    };

    let mut pid:Pid = Pid::from_u32(0);
    let flag_pid;
    match args_pid {
        Some(p) => {flag_pid = true;pid = p;},
        None => {flag_pid= false;},
    };

    let mut all_fcache:Vec<cache::Fcache> = Vec::new();
    if flag_pid {
        all_fcache = cache::get_all_fcache_by_pid(&pid);
    } else {
        all_fcache = cache::get_all_file_cached();
    }

    if flag_top {
        cache::print_fcache_vector(&all_fcache[0..top]);
    } else {
        cache::print_fcache_vector(&all_fcache);
    }
}